package br.com.freelancer.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;

/**
 * Classe utilitária para tratamentos genéricos de números
 * 
 * @author Walter Fontes
 */
public class NumeroHelper {

	//Construtor privado. Os métodos devem ser estáticos
	private NumeroHelper() {}

	/**
	 * Formata valor passado por parâmetro em formato padrão de valor brasileiro
	 * 
	 * @param valor
	 * @return
	 */
	public static String obtemValorFormatado(double valor) {
		DecimalFormat df = new DecimalFormat("#,###,###,##0.00");
		DecimalFormatSymbols dfs = new DecimalFormatSymbols();
		dfs.setDecimalSeparator(',');
		dfs.setGroupingSeparator('.');
		df.setDecimalFormatSymbols(dfs);
		return df.format(valor);
	}

	/**
	 * Formata valor passado por parâmetro em formato padrão de valor brasileiro
	 * 
	 * @param valor
	 * @return
	 */
	public static String obtemValorFormatado(BigDecimal valor) {
		if (ObjectHelper.isNotNull(valor)) {
			DecimalFormat df = new DecimalFormat("#,###,###,##0.00");
			DecimalFormatSymbols dfs = new DecimalFormatSymbols();
			dfs.setDecimalSeparator(',');
			dfs.setGroupingSeparator('.');
			df.setDecimalFormatSymbols(dfs);
			return df.format(valor);
		}else{
			return "";
		}
	}
	
	/**
	 * Formata valor passado por parâmetro em formato padrão de valor brasileiro
	 * 
	 * @param valor
	 * @return
	 */
	public static String obtemValorFormatadoBig(BigDecimal valor) {
		if (ObjectHelper.isNotNull(valor)) {
			DecimalFormat df = new DecimalFormat("#,###,###,##0.00");
			DecimalFormatSymbols dfs = new DecimalFormatSymbols();
			dfs.setDecimalSeparator(',');
			dfs.setGroupingSeparator('.');
			df.setDecimalFormatSymbols(dfs);
			return df.format(valor);
		}else{
			return "";
		}
	}

	/**
	 * Formata valor passado por parâmetro em formato padrão de valor e a escala a ser definida pelo consumidor.
	 * <strong>O tipo do local (<code>java.util.Locale</code>) é opcional. O padrão é o brasileiro.</strong>
	 * 
	 * @param valor
	 * @param scale
	 * @return retorna o valor formatado no padrão definido pelo local.
	 */
	public static String obtemValorFormatado(final String valor, final Integer scale, final Locale localMoeda) {
		if (ObjectHelper.isNotEmpty(valor)
				&& ObjectHelper.isNotEmpty(scale)) {
			final BigDecimal numero = new BigDecimal(valor); 
			final BigDecimal numeroFracao = numero.setScale(scale, RoundingMode.HALF_EVEN);
			Locale lLocalMoeda = localMoeda;
			if (ObjectHelper.isNull(localMoeda)){
				lLocalMoeda = new Locale("pt", "BR"); //Locale para o Brasil 
			}
			final NumberFormat formatoMoeda = NumberFormat.getCurrencyInstance(lLocalMoeda); 
			formatoMoeda.setMinimumFractionDigits( 1 ); 
			formatoMoeda.setMaximumFractionDigits( scale ); 
			return formatoMoeda.format(numeroFracao.doubleValue()).replace("R$", "").replace("$", "").trim(); 		
		}else{
			return "";
		}
	}

	/**
	 * Formata valor passado por parâmetro em formato padrão de valor brasileiro
	 * 
	 * @param valor
	 * @return
	 */
	public static String obtemValorSDecimaisFormatado(BigDecimal valor) {
		if (ObjectHelper.isNotNull(valor)) {

			DecimalFormat df = new DecimalFormat("#,###,###,##0");
			DecimalFormatSymbols dfs = new DecimalFormatSymbols();
			dfs.setDecimalSeparator(',');
			dfs.setGroupingSeparator('.');
			df.setDecimalFormatSymbols(dfs);
			return df.format(valor);
		}else{
			return "";
		}
		//        ((BigDecimal) map.get("dinheiro")).setScale(2).toPlainString().replaceAll("\\.", "\\,")
	}
	
	/**
	 * Formata valor passado por parâmetro em formato padrão de valor brasileiro
	 * @param valor Integer
	 * @return String Valor Formatado 
	 */
	public static String obtemValorSDecimaisFormatado(Integer valor) {
		if (ObjectHelper.isNotNull(valor)) {

			DecimalFormat df = new DecimalFormat("#,###,###,##0");
			DecimalFormatSymbols dfs = new DecimalFormatSymbols();
			dfs.setDecimalSeparator(',');
			dfs.setGroupingSeparator('.');
			df.setDecimalFormatSymbols(dfs);
			return df.format(valor);
		}else{
			return "";
		}
	}
	/**
	 * Formata valor passado por parâmetro em formato padrão de valor brasileiro
	 * 
	 * @param valor
	 * @return
	 */
	public static String obtemValorFormatadoQuatroCasas(BigDecimal valor) {
		if (ObjectHelper.isNotNull(valor)) {

			DecimalFormat df = new DecimalFormat("#,###,###,####0.0000");
			DecimalFormatSymbols dfs = new DecimalFormatSymbols();
			dfs.setDecimalSeparator(',');
			dfs.setGroupingSeparator('.');
			df.setDecimalFormatSymbols(dfs);
			return df.format(valor);
		}else{
			return "";
		}
		//        ((BigDecimal) map.get("dinheiro")).setScale(2).toPlainString().replaceAll("\\.", "\\,")
	}
	/**
	 * Retira formatação de valor
	 * 
	 * @param valor
	 * @return
	 */
	public static double obtemValorSemFormatacao(String valor) throws Exception {
		DecimalFormat df = new DecimalFormat("#,###,###,##0.00");
		DecimalFormatSymbols dfs = new DecimalFormatSymbols();
		dfs.setDecimalSeparator(',');
		dfs.setGroupingSeparator('.');
		df.setDecimalFormatSymbols(dfs);
		return df.parse(valor).doubleValue();
	}


	/**
	 * Verifica se uma String contém apenas numeros
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNumero(String str) {
		try {
			Long.parseLong(str);
		} catch (Exception e) {
			return false;
		}
		return true;
	}


	/**
	 * Verifica se uma String contém apenas numeros
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNumeroSemFormatacao(String str) {
		try {
			int localPonto = str.indexOf(".");
			if (localPonto != -1) {
				int qtdeCasas = str.length() - (localPonto+1);
				if (qtdeCasas > 2) return false;

				Long.parseLong(str.substring(0,localPonto));
				Long.parseLong(str.substring((localPonto+1), str.length()));
			} else {
				Long.parseLong(str);
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}    

	public static void main(String[] args) {
		//System.out.println(isNumeroSemFormatacao("1000.X0"));
		//System.out.println(NumeroHelper.obtemValorFormatado(new BigDecimal("4.23798")));
	}



	/**
	 * Verifica se uma String contém apenas valor
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isValor(String str) {
		try {
			obtemValorSemFormatacao(str);
		} catch (Exception e) {
			return false;
		}
		return true;
	}    

	/**
	 * valida e retorna um valor do tipo Integer
	 * 
	 * @param obj
	 * @return Integer
	 */
	public static Integer getInteger(Object obj) {


		if( obj == null || !(obj instanceof Integer))
			return new Integer(0);

		return (Integer) obj;
	}    

	/**
	 * valida e retorna um valor do tipo BigDecimal
	 * 
	 * @param obj
	 * @return BigDecimal
	 */
	public static BigDecimal getBigDecimal(Object obj) {


		if( obj == null || !(obj instanceof BigDecimal))
			return new BigDecimal(0);

		return (BigDecimal) obj;
	}    


	/**
	 * Formata valor passado por parâmetro em formato padrão de inteiro brasileiro (utiliza '.' como separador de milhar)
	 * 
	 * @param valor
	 * @return
	 */
	public static String obtemValorFormatadoInteiro(Integer valor) 
	{
		if (ObjectHelper.isNotNull(valor)) 
		{
			DecimalFormat df = new DecimalFormat("#,###,###,###");
			DecimalFormatSymbols dfs = new DecimalFormatSymbols();
			dfs.setGroupingSeparator('.');
			df.setDecimalFormatSymbols(dfs);
			return df.format(valor);
		}
		else
		{
			return "";
		}
	}
	
	/**
	 * Gera valores com zero a esquerda
	 * @param valor
	 * @param digitos
	 * @return
	 */
	public static String obtemZeroEsquerda(Integer valor,Integer digitos){
		String valorFormatado="";
		if(ObjectHelper.isNotNull(valor)){
			valorFormatado=valor.toString();
			while (valorFormatado.length() < digitos) {
				valorFormatado = "0" + valorFormatado;
			}
		}
		return valorFormatado;
	}


	/**
	 * @param total
	 * 
	 * @param parcial
	 * @return
	 */
	public static int getPercentual(Integer total, Integer parcial	) {
		return (NumeroHelper.getInteger(parcial)*100) /NumeroHelper.getInteger(total) ;
	}


}